from flask import current_app
from flask import g, jsonify
from flask import redirect
from flask import render_template
from flask import request
from flask import session
from . import profile_blu
from info.utils.commons import login_status
from info.utils.response_code import RET
from info import db, constants
from info.utils.image_storage import storage
from info.models import Category, News


# 用户信息页面
@profile_blu.route('/info')
@login_status
def user_info():
    """
    用户信息页面
    1.尝试获取用户信息
    2.如果用户不存在，则重定向到项目首页
    3.如果用户存在，则默认加载模板页面
    :return:
    """
    # 1.尝试获取用户信息
    user = g.user
    # 2.用户信息不存在重定向到项目首页
    if not user:
        return redirect('/')
    # 3.准备返回模板的用户信息数据
    data = {
        'user': user.to_dict()
    }
    # 4.默认加载模板页面
    return render_template('news/user.html', data=data)


# 用户基本信息设置
@profile_blu.route('/base_info', methods=['GET', 'POST'])
@login_status
def base_info():
    user = g.user
    # 1.判断请求方法是否是get,则加载默认的用户基本资料页面
    if request.method == 'GET':
        data = {
            'user': user.to_dict()
        }
        return render_template('news/user_base_info.html', data=data)
    # 2.请求方法为post
    # 2.1.获取参数
    nick_name = request.json.get('nick_name')
    signature = request.json.get('signature')
    gender = request.json.get('gender')
    # 2.2.校验参数是否完整
    if not all([nick_name, signature, gender]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 2.3.判断性别参数是否正确
    if gender not in ['MAN', 'WOMEN']:
        return jsonify(errno=RET.DBERR, errmsg='参数不符合要求')
    # 2.4.修改用户信息并存入数据库
    user.nick_name = nick_name
    user.signature = signature
    user.gender = gender
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='用户信息保存失败')
    # 2.5.缓存更改后的用户昵称
    session['nick_name'] = user.nick_name
    # 2.5.返回结果给前端
    return jsonify(errno=RET.OK, errmsg='修改基本资料成功')


# 上传用户头像
@profile_blu.route('/pic_info', methods=['GET', 'POST'])
@login_status
def pic_info():
    # 获取用户登录信息
    user = g.user

    # 1.判断请求方法
    if request.method == 'GET':
        data = {
            'user': user.to_dict()
        }
        return render_template('news/user_pic_info.html', data=data)
    # 2.请求方法为post
    # 2.1.获取参数
    avatar = request.files.get('avatar')
    if not avatar:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 读取图片数据
    try:
        avatar_data = avatar.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数格式错误')
    # 调用七牛云，进行文件上传
    try:
        pic_name = storage(avatar_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='上传图片失败')
    # 保存图片数据到用户数据中 保存的是图片的相对路径
    user.avatar_url = pic_name
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 拼接图片的绝对路径，七牛云的空间外链域名+图片名称
    avatar_url = constants.QINIU_DOMIN_PREFIX + pic_name
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='成功', data={'avatar_url': avatar_url})


# 密码修改模块
@profile_blu.route('/pass_info', methods=['GET', 'POST'])
@login_status
def pass_info():
    # 获取用户信息
    user = g.user
    # 判断请求方法是否为get
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')
    # 获取参数
    old_password = request.json.get('old_password')
    new_password = request.json.get('new_password')
    # 校验参数完整性
    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 判断用户是否登录
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 校验原始密码是否正确
    if not user.check_password(old_password):
        return jsonify(errno=RET.PWDERR, errmsg='密码错误')
    # 如果旧密码正确，则可以进行新密码的更改
    user.password = new_password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据保存失败')
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='密码修改成功')


# 个人中心-我的收藏模块
@profile_blu.route('/collection')
@login_status
def collection():
    # 1.获取参数 页数p 默认1
    page = request.args.get('p', 1)
    # 2.判断参数p是否是整型
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    # 3.获取用户信息 定义容器存储查询结果 总页数默认1 当前页数默认1
    user = g.user
    news_list = []
    total_page = 1
    current_page = 1
    # 4.查询数据库，从用户收藏的新闻中进行分页
    try:
        paginate = user.collection_news.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        # 获取当前页
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
        # 获取新闻数据
        news_list = paginate.items
    except Exception as e:
        current_app.logger.error(e)
    # 5.定义列表容器，遍历查询结果并转换为字典格式的添加到列表中
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_basic_dict())
    # 6.准备返回的数据
    data = {
        'collections': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }
    # 7.返回数据
    return render_template('news/user_collection.html', data=data)


# 个人中心-用户新闻列表
@profile_blu.route('/news_list')
@login_status
def news_list():
    # 1.获取参数 页数p 默认1
    page = request.args.get('p', 1)
    # 2.将参数p转换成整型
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    # 3.获取用户信息 定义容器储存查询对象 定义当前页/总页数 默认均为1
    user = g.user
    news_list = []
    current_page = 1
    total_page = 1
    # 4.分页查询
    try:
        paginate = user.news_list.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        # 获取当前页数据
        news_list = paginate.items
        # 获取当前页
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)

    # 5.遍历查询的新闻对象并转成字典类型，定义一容器进行存储
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())

    # 6.准备要返回给模板的数据
    data = {
        'news': news_dict_list,
        'current_page': current_page,
        'total_page': total_page
    }
    return render_template('news/user_news_list.html', data=data)


# 个人中心-新闻发布
@profile_blu.route('/news_release', methods=['GET', 'POST'])
@login_status
def news_release():
    # 获取用户信息
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 1.判断请求方法是否为get
    if request.method == 'GET':
        # 进行分类查询 查询所有分类
        try:
            categories = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询错误')
        # 判断查询结果是否存在
        if not categories:
            return jsonify(errno=RET.NODATA, errmsg='查询无结果')
        # 准备一个列表容器用于存储遍历查询结果后转换的字典数据
        category_list = []
        for category in categories:
            category_list.append(category.to_dict())
        # 弹出id=1(最新)的类别
        category_list.pop(0)
        # 准备传给模板的数据
        data = {
            'category_list': category_list
        }
        # 返回给模板
        return render_template('news/user_news_release.html', data=data)
    # 请求方法为post请求
    # 1.获取参数
    title = request.form.get('title')
    category_id = request.form.get('category_id')
    digest = request.form.get('digest')
    index_image = request.files.get('index_image')
    content = request.form.get('content')
    print(content)
    # 2.校验参数完整性
    if not all([title, category_id, digest, index_image, content]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 3.将分类id转换成整型
    try:
        category_id = int(category_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='参数格式错误')
    # 4.读取图片内容，使用七牛云上传图片
    try:
        index_image_data = index_image.read()
        image_name = storage(index_image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='上传图片失败')
    # 5.构造模型类 存储新闻数据
    news = News()
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + image_name
    news.content = content
    news.user_id = user.id
    news.status = 1
    news.source = '个人发布'
    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据保存失败')
    # 6.返回结果
    return jsonify(errno=RET.OK, errmsg='新闻发布成功')
